Imports System.Xml
Imports DaveSexton.DocProject.DocSites

Partial Public Class DocSiteIndex
	Inherits System.Web.UI.UserControl
	Implements IPostBackEventHandler

	<System.ComponentModel.Browsable(False)> _
 Public Property SelectedHelpFile() As String
		Get
			Dim value As String = CType(ViewState("_$SelectedHelpFile"), String)

			If value Is Nothing Then
				Return String.Empty
			Else
				Return value
			End If
		End Get
		Set(ByVal value As String)
			If value <> CType(ViewState("_$SelectedHelpFile"), String) Then
				ViewState("_$SelectedHelpFile") = value

				RaiseEvent SelectedHelpFileChanged(Me, EventArgs.Empty)
			End If
		End Set
	End Property

	<System.ComponentModel.Category("Behavior"), System.ComponentModel.DefaultValue(""), _
	System.ComponentModel.Description("Filters the index so that it only displays entries that are like the specified value.")> _
	Public Property Filter() As String
		Get
			Dim value As String = CType(ViewState("_$Filter"), String)

			If value Is Nothing Then
				Return String.Empty
			Else
				Return value
			End If
		End Get
		Set(ByVal value As String)
			ViewState("_$Filter") = value
		End Set
	End Property

	Protected Shared ReadOnly Property ItemList() As List(Of Item)
		Get
			SyncLock sync
				If _ItemList Is Nothing Then
					_ItemList = LoadIndex()
				End If
			End SyncLock

			Return _ItemList
		End Get
	End Property

	Protected ReadOnly Property FilteredItemList() As List(Of Item)
		Get
			Dim _filter As String = Filter

			Dim results As List(Of Item) = New List(Of Item)()

			If String.IsNullOrEmpty(_filter) Then
				Return results
			Else
				_filter = _filter.Trim()

				If _filter.Length = 0 Then
					Return results
				End If
			End If

			Dim _list As List(Of Item) = ItemList

			Dim keywords As String() = _filter.Split(New Char() {CChar(" "), CChar("."), CChar(",")}, StringSplitOptions.RemoveEmptyEntries)

			If keywords.Length = 0 Then
				Return results
			End If

			For Each _item As Item In _list
				Dim words As List(Of String) = New List(Of String)( _
				 _item.Name.Split(New Char() {CChar(" "), CChar("."), CChar(",")}, StringSplitOptions.RemoveEmptyEntries))

				Dim allKeywordsFound As Boolean = True

				For Each keyword As String In keywords
					Dim keywordFound As Boolean = False

					For Each word As String In words
						If word.Equals(keyword, StringComparison.CurrentCultureIgnoreCase) Then
							keywordFound = True
							Exit For
						End If
					Next

					If Not keywordFound Then
						allKeywordsFound = False
						Exit For
					End If
				Next

				If allKeywordsFound Then
					results.Add(_item)
				End If
			Next

			Return results
		End Get
	End Property

	''' <summary>
	''' This field is used by the repeater control's item template to store whether the current item is selected while iterating through the index.
	''' </summary>
	Protected currentItemSelected As Boolean
	Private Shared ReadOnly sync As Object = New Object()
	Private Shared _ItemList As List(Of Item)

	Private Shared Function LoadIndex() As List(Of Item)
		Dim context As HttpContext = HttpContext.Current

		If context Is Nothing Then
			Throw New InvalidOperationException("The LoadIndex method, which initializes the DocSite index, cannot be called outside of a request context.")
		End If

		Dim _items As List(Of Item) = New List(Of Item)

		Dim settings As XmlReaderSettings = New XmlReaderSettings()
		With settings
			.IgnoreComments = True
			.IgnoreProcessingInstructions = True
			.IgnoreWhitespace = True
		End With

		Using reader As XmlReader = XmlReader.Create( _
		 context.Server.MapPath(DocSiteManager.Settings.DocSiteIndexXmlSource), settings)

			reader.MoveToContent()

			While reader.Read
				If Not reader.IsStartElement("entry") Then
					Continue While
				End If

				Dim name As String = reader.GetAttribute("name")
				Dim file As String = reader.GetAttribute("file")

				_items.Add(New Item(name, file))
			End While
		End Using

		_items.Sort(AddressOf SortItems)

		Return _items
	End Function

	Private Shared Function SortItems(ByVal item1 As Item, ByVal item2 As Item) As Integer
		Return String.Compare(item1.Name, item2.Name, StringComparison.CurrentCulture)
	End Function

	Protected Function GetPostBackClientHyperlink(ByVal file As String) As String
		Return Page.ClientScript.GetPostBackClientHyperlink(Me, file, False).Replace(CChar("'"), CChar(""""))
	End Function

	Protected Function EvaluateCurrentItemSelected(ByVal file As String) As String
		currentItemSelected = SelectedHelpFile.Equals(file, StringComparison.Ordinal)

		If currentItemSelected Then
			Return "index_item_selected"
		Else
			Return "index_item"
		End If
	End Function

	Public Event SelectedHelpFileChanged(ByVal sender As Object, ByVal e As EventArgs)

	Protected Sub indexFilterButton_Click(ByVal sender As Object, ByVal e As ImageClickEventArgs)
		Filter = indexFilterTextBox.Text
	End Sub

	Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
		indexFilterTextBox.Attributes.Add("onkeypress", "checkSubmitOnEnter(event, document.getElementById('" & indexFilterButton.ClientID & "'));")

		indexFilterDiv.Visible = indexFilterCheckbox.Checked

		If indexFilterCheckbox.Checked Then
			indexRepeater.DataSource = FilteredItemList
		Else
			indexRepeater.DataSource = ItemList
		End If

		indexRepeater.DataBind()

		index_list_container.Attributes.Add("class", CStr(IIf(indexFilterCheckbox.Checked, "index_list index_list_filtered", "index_list")))

		MyBase.OnPreRender(e)
	End Sub

	Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
		SelectedHelpFile = eventArgument
	End Sub

	Protected Structure Item
		Implements IEquatable(Of Item)

		Public ReadOnly Property File() As String
			Get
				Return _File
			End Get
		End Property

		Public ReadOnly Property Name() As String
			Get
				Return _Name
			End Get
		End Property

		Private ReadOnly _File, _Name As String

		Public Sub New(ByVal name As String, ByVal file As String)
			_Name = name
			_File = file
		End Sub

		Public Overrides Function Equals(ByVal obj As Object) As Boolean
			If TypeOf obj Is Item Then
				Return Equals(CType(obj, Item))
			Else
				Return False
			End If
		End Function

		Public Overrides Function GetHashCode() As Integer
			Return _Name.GetHashCode() Xor _File.GetHashCode()
		End Function

		Public Overrides Function ToString() As String
			Return _Name
		End Function

		Public Shared Operator =(ByVal i1 As Item, ByVal i2 As Item) As Boolean
			Return i1.Equals(i2)
		End Operator

		Public Shared Operator <>(ByVal i1 As Item, ByVal i2 As Item) As Boolean
			Return Not i1.Equals(i2)
		End Operator

		Public Overloads Function Equals(ByVal other As Item) As Boolean Implements System.IEquatable(Of Item).Equals
			Return String.Equals(other._File, _File, StringComparison.Ordinal) AndAlso String.Equals(other._Name, _Name, StringComparison.Ordinal)
		End Function
	End Structure
End Class